#include <xeroskernel.h>
#include <kbd.h>

extern void init_device(){
	devtab[CONSOLE].dvnum = CONSOLE;
	devtab[CONSOLE].dvopen = kbdopen_nonecho;
	devtab[CONSOLE].dvclose = kbdclose;
	devtab[CONSOLE].dvwrite = kbdwrite;
	devtab[CONSOLE].dvread = kbdread;
	devtab[CONSOLE].dvioctl = kbdioctl;

	devtab[KEYBOARD].dvnum = KEYBOARD;
	devtab[KEYBOARD].dvopen = kbdopen_echo;
	devtab[KEYBOARD].dvclose = kbdclose;
	devtab[KEYBOARD].dvwrite = kbdwrite;
	devtab[KEYBOARD].dvread = kbdread;
	devtab[KEYBOARD].dvioctl = kbdioctl;
}

extern int di_open(pcb *p, int device_no){
	//if device number is within range, opens device and returns available file descriptor
	//otherwise returns -1
	if(device_no < 0 || device_no >= MAX_DEV)
		return -1;

	int i;
	for(i=0; i<MAX_FD; i++){
		if(p->fd_table[i].device == NULL){
			if(devtab[device_no].dvopen() == 0){
				devtab[device_no].owner = p;
				p->fd_table[i].device = &devtab[device_no];
				return i;	
			}else{
				return -1;
			}
		}
	}
	
	return -1;
}

extern int di_close(pcb *p, int fd){
	//close device if device is within fd range
	//returns 0 if successful, -1 otherwise
	if(fd < 0 || fd >= MAX_FD || p->fd_table[fd].device == NULL)
		return -1;
		
	if( p->fd_table[fd].device->dvclose() == 0 ){
		devtab[p->fd_table[fd].device->dvnum].owner = NULL;
		p->fd_table[fd].device = NULL;
		return 0;	
	}else{
		return -1;
	}
}

extern int di_write(pcb *p, int fd, void *buff, int bufflen){
	//performs a write to device	
	if(fd < 0 || fd >= MAX_FD || p->fd_table[fd].device == NULL)
		return -1;

	devsw *devptr = p->fd_table[fd].device;	
	return (*devptr->dvwrite)(p, buff, bufflen);	
}

extern int di_read(pcb *p, int fd, void *buff, int bufflen){
	//performs a read from device
	if(fd < 0 || fd >= MAX_FD || p->fd_table[fd].device == NULL)
		return -1;

	devsw *devptr = p->fd_table[fd].device;	
	return (*devptr->dvread)(p, buff, bufflen);
}

extern int di_ioctl(pcb *p, int fd, unsigned long command, ...){
	//executes command for device
	if(fd < 0 || fd >= MAX_FD || p->fd_table[fd].device == NULL)
		return -1;

	devsw *devptr = p->fd_table[fd].device;	
	void *args = &command + 1;
	return (*devptr->dvioctl)(p, command, args);
}


